home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / MacPerl ƒ / Perl Source ƒ / Perl / cmd.c < prev    next >
Text File  |  1993-12-20  |  31KB  |  1,323 lines

  1. /* $RCSfile: cmd.c,v $$Revision: 4.0.1.5 $$Date: 92/06/08 12:00:39 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of the Perl Artistic License,
  6.  *    as specified in the README file.
  7.  *
  8.  * $Log:    cmd.c,v $
  9.  * Revision 4.0.1.5  92/06/08  12:00:39  lwall
  10.  * patch20: the switch optimizer didn't do anything in subroutines
  11.  * patch20: removed implicit int declarations on funcions
  12.  * 
  13.  * Revision 4.0.1.4  91/11/11  16:29:33  lwall
  14.  * patch19: do {$foo ne "bar";} returned wrong value
  15.  * patch19: some earlier patches weren't propagated to alternate 286 code
  16.  * 
  17.  * Revision 4.0.1.3  91/11/05  16:07:43  lwall
  18.  * patch11: random cleanup
  19.  * patch11: "foo\0" eq "foo" was sometimes optimized to true
  20.  * patch11: foreach on null list could spring memory leak
  21.  * 
  22.  * Revision 4.0.1.2  91/06/07  10:26:45  lwall
  23.  * patch4: new copyright notice
  24.  * patch4: made some allowances for "semi-standard" C
  25.  * 
  26.  * Revision 4.0.1.1  91/04/11  17:36:16  lwall
  27.  * patch1: you may now use "die" and "caller" in a signal handler
  28.  * 
  29.  * Revision 4.0  91/03/20  01:04:18  lwall
  30.  * 4.0 baseline.
  31.  * 
  32.  */
  33.  
  34. #include "EXTERN.h"
  35. #include "perl.h"
  36.  
  37. #ifdef I_VARARGS
  38. #  include <varargs.h>
  39. #endif
  40.  
  41. static STR strchop;
  42.  
  43. void grow_dlevel();
  44.  
  45. /* do longjmps() clobber register variables? */
  46.  
  47. #if defined(cray) || defined(STDMAC)
  48. #define JMPCLOBBER
  49. #endif
  50.  
  51. /* This is the main command loop.  We try to spend as much time in this loop
  52.  * as possible, so lots of optimizations do their activities in here.  This
  53.  * means things get a little sloppy.
  54.  */
  55.  
  56. int
  57. cmd_exec(cmdparm,gimme,sp)
  58. CMD *VOLATILE cmdparm;
  59. VOLATILE int gimme;
  60. VOLATILE int sp;
  61. {
  62.     register CMD *cmd = cmdparm;
  63.     SPAT *VOLATILE oldspat;
  64.     VOLATILE int firstsave = savestack->ary_fill;
  65.     VOLATILE int oldsave;
  66.     VOLATILE int aryoptsave;
  67. #ifdef DEBUGGING
  68.     VOLATILE int olddlevel;
  69.     VOLATILE int entdlevel;
  70. #endif
  71.     register STR *retstr = &str_undef;
  72.     register char *tmps;
  73.     register int cmdflags;
  74.     register int match;
  75.     register char *go_to = goto_targ;
  76.     register int newsp = -2;
  77.     register STR **st = stack->ary_array;
  78.     FILE *VOLATILE fp;
  79.     ARRAY *VOLATILE ar;
  80.  
  81.     lastsize = 0;
  82. #ifdef DEBUGGING
  83.     entdlevel = dlevel;
  84. #endif
  85. tail_recursion_entry:
  86.  
  87. #ifdef macintosh
  88.     SpinMacCursor();
  89. #endif
  90.  
  91. #ifdef DEBUGGING
  92.     dlevel = entdlevel;
  93.     if (debug & 4)
  94.     deb("mortals = (%d/%d) stack, = (%d/%d)\n",
  95.         tmps_max, tmps_base,
  96.         savestack->ary_fill, firstsave);
  97. #endif
  98. #ifdef TAINT
  99.     tainted = 0;    /* Each statement is presumed innocent */
  100. #endif
  101.     if (cmd == Nullcmd) {
  102.     if (gimme == G_ARRAY && newsp > -2)
  103.         return newsp;
  104.     else {
  105.         st[++sp] = retstr;
  106.         return sp;
  107.     }
  108.     }
  109.     cmdflags = cmd->c_flags;    /* hopefully load register */
  110.     if (go_to) {
  111.     if (cmd->c_label && strEQ(go_to,cmd->c_label))
  112.         goto_targ = go_to = Nullch;        /* here at last */
  113.     else {
  114.  
  115. #ifdef macintosh
  116.    SpinMacCursor();
  117. #endif
  118.  
  119.         switch (cmd->c_type) {
  120.         case C_IF:
  121.         oldspat = curspat;
  122.         oldsave = savestack->ary_fill;
  123. #ifdef DEBUGGING
  124.         olddlevel = dlevel;
  125. #endif
  126.         retstr = &str_yes;
  127.         newsp = -2;
  128.         if (cmd->ucmd.ccmd.cc_true) {
  129. #ifdef DEBUGGING
  130.             if (debug) {
  131.             debname[dlevel] = 't';
  132.             debdelim[dlevel] = '_';
  133.             if (++dlevel >= dlmax)
  134.                 grow_dlevel();
  135.             }
  136. #endif
  137.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  138.             st = stack->ary_array;    /* possibly reallocated */
  139.             retstr = st[newsp];
  140.         }
  141.         if (!goto_targ)
  142.             go_to = Nullch;
  143.         curspat = oldspat;
  144.         if (savestack->ary_fill > oldsave)
  145.             restorelist(oldsave);
  146. #ifdef DEBUGGING
  147.         dlevel = olddlevel;
  148. #endif
  149.         cmd = cmd->ucmd.ccmd.cc_alt;
  150.         goto tail_recursion_entry;
  151.         case C_ELSE:
  152.         oldspat = curspat;
  153.         oldsave = savestack->ary_fill;
  154. #ifdef DEBUGGING
  155.         olddlevel = dlevel;
  156. #endif
  157.         retstr = &str_undef;
  158.         newsp = -2;
  159.         if (cmd->ucmd.ccmd.cc_true) {
  160. #ifdef DEBUGGING
  161.             if (debug) {
  162.             debname[dlevel] = 'e';
  163.             debdelim[dlevel] = '_';
  164.             if (++dlevel >= dlmax)
  165.                 grow_dlevel();
  166.             }
  167. #endif
  168.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  169.             st = stack->ary_array;    /* possibly reallocated */
  170.             retstr = st[newsp];
  171.         }
  172.         if (!goto_targ)
  173.             go_to = Nullch;
  174.         curspat = oldspat;
  175.         if (savestack->ary_fill > oldsave)
  176.             restorelist(oldsave);
  177. #ifdef DEBUGGING
  178.         dlevel = olddlevel;
  179. #endif
  180.         break;
  181.         case C_BLOCK:
  182.         case C_WHILE:
  183.         if (!(cmdflags & CF_ONCE)) {
  184.             cmdflags |= CF_ONCE;
  185.             if (++loop_ptr >= loop_max) {
  186.             loop_max += 128;
  187.             Renew(loop_stack, loop_max, struct loop);
  188.             }
  189.             loop_stack[loop_ptr].loop_label = cmd->c_label;
  190.             loop_stack[loop_ptr].loop_sp = sp;
  191. #ifdef DEBUGGING
  192.             if (debug & 4) {
  193.             deb("(Pushing label #%d %s)\n",
  194.               loop_ptr, cmd->c_label ? cmd->c_label : "");
  195.             }
  196. #endif
  197.         }
  198. #ifdef JMPCLOBBER
  199.         cmdparm = cmd;
  200. #endif
  201.         match = setjmp(loop_stack[loop_ptr].loop_env);
  202.         if (match) {
  203.             st = stack->ary_array;    /* possibly reallocated */
  204. #ifdef JMPCLOBBER
  205.             cmd = cmdparm;
  206.             cmdflags = cmd->c_flags|CF_ONCE;
  207. #endif
  208.             if (savestack->ary_fill > oldsave)
  209.             restorelist(oldsave);
  210.             switch (match) {
  211.             default:
  212.             fatal("longjmp returned bad value (%d)",match);
  213.             case O_LAST:    /* not done unless go_to found */
  214.             go_to = Nullch;
  215.             if (lastretstr) {
  216.                 retstr = lastretstr;
  217.                 newsp = -2;
  218.             }
  219.             else {
  220.                 newsp = sp + lastsize;
  221.                 retstr = st[newsp];
  222.             }
  223. #ifdef DEBUGGING
  224.             olddlevel = dlevel;
  225. #endif
  226.             curspat = oldspat;
  227.             goto next_cmd;
  228.             case O_NEXT:    /* not done unless go_to found */
  229.             go_to = Nullch;
  230. #ifdef JMPCLOBBER
  231.             newsp = -2;
  232.             retstr = &str_undef;
  233. #endif
  234.             goto next_iter;
  235.             case O_REDO:    /* not done unless go_to found */
  236.             go_to = Nullch;
  237. #ifdef JMPCLOBBER
  238.             newsp = -2;
  239.             retstr = &str_undef;
  240. #endif
  241.             goto doit;
  242.             }
  243.         }
  244.         oldspat = curspat;
  245.         oldsave = savestack->ary_fill;
  246. #ifdef DEBUGGING
  247.         olddlevel = dlevel;
  248. #endif
  249.         if (cmd->ucmd.ccmd.cc_true) {
  250. #ifdef DEBUGGING
  251.             if (debug) {
  252.             debname[dlevel] = 't';
  253.             debdelim[dlevel] = '_';
  254.             if (++dlevel >= dlmax)
  255.                 grow_dlevel();
  256.             }
  257. #endif
  258.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  259.             st = stack->ary_array;    /* possibly reallocated */
  260.             if (newsp >= 0)
  261.             retstr = st[newsp];
  262.         }
  263.         if (!goto_targ) {
  264.             go_to = Nullch;
  265.             goto next_iter;
  266.         }
  267. #ifdef DEBUGGING
  268.         dlevel = olddlevel;
  269. #endif
  270.         if (cmd->ucmd.ccmd.cc_alt) {
  271. #ifdef DEBUGGING
  272.             if (debug) {
  273.             debname[dlevel] = 'a';
  274.             debdelim[dlevel] = '_';
  275.             if (++dlevel >= dlmax)
  276.                 grow_dlevel();
  277.             }
  278. #endif
  279.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  280.             st = stack->ary_array;    /* possibly reallocated */
  281.             if (newsp >= 0)
  282.             retstr = st[newsp];
  283.         }
  284.         if (goto_targ)
  285.             break;
  286.         go_to = Nullch;
  287.         goto finish_while;
  288.         }
  289.         cmd = cmd->c_next;
  290.         if (cmd && cmd->c_head == cmd)
  291.                     /* reached end of while loop */
  292.         return sp;        /* targ isn't in this block */
  293.         if (cmdflags & CF_ONCE) {
  294. #ifdef DEBUGGING
  295.         if (debug & 4) {
  296.             tmps = loop_stack[loop_ptr].loop_label;
  297.             deb("(Popping label #%d %s)\n",loop_ptr,
  298.             tmps ? tmps : "" );
  299.         }
  300. #endif
  301.         loop_ptr--;
  302.         }
  303.         goto tail_recursion_entry;
  304.     }
  305.     }
  306.  
  307. until_loop:
  308.  
  309. #ifdef macintosh
  310.     SpinMacCursor();
  311. #endif
  312.  
  313.     /* Set line number so run-time errors can be located */
  314.  
  315.     curcmd = cmd;
  316.  
  317. #ifdef DEBUGGING
  318.     if (debug) {
  319.     if (debug & 2) {
  320.         deb("%s    (%lx)    r%lx    t%lx    a%lx    n%lx    cs%lx\n",
  321.         cmdname[cmd->c_type],cmd,cmd->c_expr,
  322.         cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
  323.         curspat);
  324.     }
  325.     debname[dlevel] = cmdname[cmd->c_type][0];
  326.     debdelim[dlevel] = '!';
  327.     if (++dlevel >= dlmax)
  328.         grow_dlevel();
  329.     }
  330. #endif
  331.  
  332. #ifdef macintosh
  333.     SpinMacCursor();
  334. #endif
  335.  
  336.     /* Here is some common optimization */
  337.  
  338.     if (cmdflags & CF_COND) {
  339.     switch (cmdflags & CF_OPTIMIZE) {
  340.  
  341.     case CFT_FALSE:
  342.         retstr = cmd->c_short;
  343.         newsp = -2;
  344.         match = FALSE;
  345.         if (cmdflags & CF_NESURE)
  346.         goto maybe;
  347.         break;
  348.     case CFT_TRUE:
  349.         retstr = cmd->c_short;
  350.         newsp = -2;
  351.         match = TRUE;
  352.         if (cmdflags & CF_EQSURE)
  353.         goto flipmaybe;
  354.         break;
  355.  
  356.     case CFT_REG:
  357.         retstr = STAB_STR(cmd->c_stab);
  358.         newsp = -2;
  359.         match = str_true(retstr);    /* => retstr = retstr, c2 should fix */
  360.         if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
  361.         goto flipmaybe;
  362.         break;
  363.  
  364.     case CFT_ANCHOR:    /* /^pat/ optimization */
  365.         if (multiline) {
  366.         if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
  367.             goto scanner;    /* just unanchor it */
  368.         else
  369.             break;        /* must evaluate */
  370.         }
  371.         match = 0;
  372.         goto strop;
  373.  
  374.     case CFT_STROP:        /* string op optimization */
  375.         match = 1;
  376.       strop:
  377.         retstr = STAB_STR(cmd->c_stab);
  378.         newsp = -2;
  379. #ifndef I286
  380.         if (*cmd->c_short->str_ptr == *str_get(retstr) &&
  381.             (match ? retstr->str_cur == cmd->c_slen - 1 :
  382.                      retstr->str_cur >= cmd->c_slen) &&
  383.             bcmp(cmd->c_short->str_ptr, str_get(retstr),
  384.               cmd->c_slen) == 0 ) {
  385.         if (cmdflags & CF_EQSURE) {
  386.             if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  387.             curspat = Nullspat;
  388.             if (leftstab)
  389.                 str_nset(stab_val(leftstab),"",0);
  390.             if (amperstab)
  391.                 str_sset(stab_val(amperstab),cmd->c_short);
  392.             if (rightstab)
  393.                 str_nset(stab_val(rightstab),
  394.                   retstr->str_ptr + cmd->c_slen,
  395.                   retstr->str_cur - cmd->c_slen);
  396.             }
  397.             if (cmd->c_spat)
  398.             lastspat = cmd->c_spat;
  399.             match = !(cmdflags & CF_FIRSTNEG);
  400.             retstr = match ? &str_yes : &str_no;
  401.             goto flipmaybe;
  402.         }
  403.         }
  404.         else if (cmdflags & CF_NESURE) {
  405.         match = cmdflags & CF_FIRSTNEG;
  406.         retstr = match ? &str_yes : &str_no;
  407.         goto flipmaybe;
  408.         }
  409. #else
  410.         {
  411.         char *zap1, *zap2, zap1c, zap2c;
  412.         int  zaplen;
  413.         int lenok;
  414.  
  415.         zap1 = cmd->c_short->str_ptr;
  416.         zap2 = str_get(retstr);
  417.         zap1c = *zap1;
  418.         zap2c = *zap2;
  419.         zaplen = cmd->c_slen;
  420.         if (match)
  421.             lenok = (retstr->str_cur == cmd->c_slen - 1);
  422.         else
  423.             lenok = (retstr->str_cur >= cmd->c_slen);
  424.         if ((zap1c == zap2c) && lenok && (bcmp(zap1, zap2, zaplen) == 0)) {
  425.             if (cmdflags & CF_EQSURE) {
  426.             if (sawampersand &&
  427.               (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  428.                 curspat = Nullspat;
  429.                 if (leftstab)
  430.                 str_nset(stab_val(leftstab),"",0);
  431.                 if (amperstab)
  432.                 str_sset(stab_val(amperstab),cmd->c_short);
  433.                 if (rightstab)
  434.                 str_nset(stab_val(rightstab),
  435.                      retstr->str_ptr + cmd->c_slen,
  436.                      retstr->str_cur - cmd->c_slen);
  437.             }
  438.             if (cmd->c_spat)
  439.                 lastspat = cmd->c_spat;
  440.              match = !(cmdflags & CF_FIRSTNEG);
  441.             retstr = match ? &str_yes : &str_no;
  442.              goto flipmaybe;
  443.             }
  444.         }
  445.         else if (cmdflags & CF_NESURE) {
  446.             match = cmdflags & CF_FIRSTNEG;
  447.             retstr = match ? &str_yes : &str_no;
  448.             goto flipmaybe;
  449.         }
  450.         }
  451. #endif
  452.         break;            /* must evaluate */
  453.  
  454.     case CFT_SCAN:            /* non-anchored search */
  455.       scanner:
  456.         retstr = STAB_STR(cmd->c_stab);
  457.         newsp = -2;
  458.         if (retstr->str_pok & SP_STUDIED)
  459.         if (screamfirst[cmd->c_short->str_rare] >= 0)
  460.             tmps = screaminstr(retstr, cmd->c_short);
  461.         else
  462.             tmps = Nullch;
  463.         else {
  464.         tmps = str_get(retstr);        /* make sure it's pok */
  465. #ifndef lint
  466.         tmps = fbminstr((unsigned char*)tmps,
  467.             (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
  468. #endif
  469.         }
  470.         if (tmps) {
  471.         if (cmdflags & CF_EQSURE) {
  472.             ++cmd->c_short->str_u.str_useful;
  473.             if (sawampersand) {
  474.             curspat = Nullspat;
  475.             if (leftstab)
  476.                 str_nset(stab_val(leftstab),retstr->str_ptr,
  477.                   tmps - retstr->str_ptr);
  478.             if (amperstab)
  479.                 str_nset(stab_val(amperstab),
  480.                   tmps, cmd->c_short->str_cur);
  481.             if (rightstab)
  482.                 str_nset(stab_val(rightstab),
  483.                   tmps + cmd->c_short->str_cur,
  484.                   retstr->str_cur - (tmps - retstr->str_ptr) -
  485.                 cmd->c_short->str_cur);
  486.             }
  487.             lastspat = cmd->c_spat;
  488.             match = !(cmdflags & CF_FIRSTNEG);
  489.             retstr = match ? &str_yes : &str_no;
  490.             goto flipmaybe;
  491.         }
  492.         else
  493.             hint = tmps;
  494.         }
  495.         else {
  496.         if (cmdflags & CF_NESURE) {
  497.             ++cmd->c_short->str_u.str_useful;
  498.             match = cmdflags & CF_FIRSTNEG;
  499.             retstr = match ? &str_yes : &str_no;
  500.             goto flipmaybe;
  501.         }
  502.         }
  503.         if (--cmd->c_short->str_u.str_useful < 0) {
  504.         cmdflags &= ~CF_OPTIMIZE;
  505.         cmdflags |= CFT_EVAL;    /* never try this optimization again */
  506.         cmd->c_flags = (cmdflags & ~CF_ONCE);
  507.         }
  508.         break;            /* must evaluate */
  509.  
  510.     case CFT_NUMOP:        /* numeric op optimization */
  511.         retstr = STAB_STR(cmd->c_stab);
  512.         newsp = -2;
  513.         switch (cmd->c_slen) {
  514.         case O_EQ:
  515.         if (dowarn) {
  516.             if ((!retstr->str_nok && !looks_like_number(retstr)))
  517.             warn("Possible use of == on string value");
  518.         }
  519.         match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
  520.         break;
  521.         case O_NE:
  522.         match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
  523.         break;
  524.         case O_LT:
  525.         match = (str_gnum(retstr) <  cmd->c_short->str_u.str_nval);
  526.         break;
  527.         case O_LE:
  528.         match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
  529.         break;
  530.         case O_GT:
  531.         match = (str_gnum(retstr) >  cmd->c_short->str_u.str_nval);
  532.         break;
  533.         case O_GE:
  534.         match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
  535.         break;
  536.         }
  537.         if (match) {
  538.         if (cmdflags & CF_EQSURE) {
  539.             retstr = &str_yes;
  540.             goto flipmaybe;
  541.         }
  542.         }
  543.         else if (cmdflags & CF_NESURE) {
  544.         retstr = &str_no;
  545.         goto flipmaybe;
  546.         }
  547.         break;            /* must evaluate */
  548.  
  549.     case CFT_INDGETS:        /* while (<$foo>) */
  550.         last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
  551.         if (!stab_io(last_in_stab))
  552.         stab_io(last_in_stab) = stio_new();
  553.         goto dogets;
  554.     case CFT_GETS:            /* really a while (<file>) */
  555.         last_in_stab = cmd->c_stab;
  556.       dogets:
  557.         fp = stab_io(last_in_stab)->ifp;
  558.         retstr = stab_val(defstab);
  559.         newsp = -2;
  560.       keepgoing:
  561.         if (fp && str_gets(retstr, fp, 0)) {
  562.         if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
  563.             match = FALSE;
  564.         else
  565.             match = TRUE;
  566.         stab_io(last_in_stab)->lines++;
  567.         }
  568.         else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  569.         if (!fp)
  570.             goto doeval;    /* first time through */
  571.         fp = nextargv(last_in_stab);
  572.         if (fp)
  573.             goto keepgoing;
  574.         (void)do_close(last_in_stab,FALSE);
  575.         stab_io(last_in_stab)->flags |= IOF_START;
  576.         retstr = &str_undef;
  577.         match = FALSE;
  578.         }
  579.         else {
  580.         retstr = &str_undef;
  581.         match = FALSE;
  582.         }
  583.         goto flipmaybe;
  584.     case CFT_EVAL:
  585.         break;
  586.     case CFT_UNFLIP:
  587.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  588.         str_free(tmps_list[tmps_max]);
  589.         tmps_list[tmps_max--] = Nullstr;
  590.         }
  591.         newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
  592.         st = stack->ary_array;    /* possibly reallocated */
  593.         retstr = st[newsp];
  594.         match = str_true(retstr);
  595.         if (cmd->c_expr->arg_type == O_FLIP)    /* undid itself? */
  596.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  597.         goto maybe;
  598.     case CFT_CHOP:
  599.         retstr = stab_val(cmd->c_stab);
  600.         newsp = -2;
  601.         match = (retstr->str_cur != 0);
  602.         tmps = str_get(retstr);
  603.         tmps += retstr->str_cur - match;
  604.         str_nset(&strchop,tmps,match);
  605.         *tmps = '\0';
  606.         retstr->str_nok = 0;
  607.         retstr->str_cur = tmps - retstr->str_ptr;
  608.         STABSET(retstr);
  609.         retstr = &strchop;
  610.          goto flipmaybe;
  611.     case CFT_ARRAY:
  612.         match = cmd->c_short->str_u.str_useful; /* just to get register */
  613.  
  614.         if (match < 0) {        /* first time through here? */
  615.         ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
  616.         aryoptsave = savestack->ary_fill;
  617.         savesptr(&stab_val(cmd->c_stab));
  618.         savelong(&cmd->c_short->str_u.str_useful);
  619.         }
  620.         else {
  621.         ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
  622.         if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave)
  623.             restorelist(firstsave);
  624.         }
  625.  
  626.         if (match >= ar->ary_fill) {    /* we're in LAST, probably */
  627.         if (match < 0 &&        /* er, probably not... */
  628.           savestack->ary_fill > aryoptsave)
  629.             restorelist(aryoptsave);
  630.         retstr = &str_undef;
  631.         cmd->c_short->str_u.str_useful = -1;    /* actually redundant */
  632.         match = FALSE;
  633.         }
  634.         else {
  635.         match++;
  636.         if (!(retstr = ar->ary_array[match]))
  637.             retstr = afetch(ar,match,TRUE);
  638.         stab_val(cmd->c_stab) = retstr;
  639.         cmd->c_short->str_u.str_useful = match;
  640.         match = TRUE;
  641.         }
  642.         newsp = -2;
  643.         goto maybe;
  644.     case CFT_D1:
  645.         break;
  646.     case CFT_D0:
  647.         if (DBsingle->str_u.str_nval != 0)
  648.         break;
  649.         if (DBsignal->str_u.str_nval != 0)
  650.         break;
  651.         if (DBtrace->str_u.str_nval != 0)
  652.         break;
  653.         goto next_cmd;
  654.     }
  655.  
  656.     /* we have tried to make this normal case as abnormal as possible */
  657.  
  658.     doeval:
  659.  
  660. #ifdef macintosh
  661.     SpinMacCursor();
  662. #endif
  663.  
  664.     if (gimme == G_ARRAY) {
  665.         lastretstr = Nullstr;
  666.         lastspbase = sp;
  667.         lastsize = newsp - sp;
  668.         if (lastsize < 0)
  669.         lastsize = 0;
  670.     }
  671.     else
  672.         lastretstr = retstr;
  673.     while (tmps_max > tmps_base) {    /* clean up after last eval */
  674.         str_free(tmps_list[tmps_max]);
  675.         tmps_list[tmps_max--] = Nullstr;
  676.     }
  677.     newsp = eval(cmd->c_expr,
  678.       gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR &&
  679.         !cmd->ucmd.acmd.ac_expr,
  680.       sp);
  681.     st = stack->ary_array;    /* possibly reallocated */
  682.     retstr = st[newsp];
  683.     if (newsp > sp && retstr)
  684.         match = str_true(retstr);
  685.     else
  686.         match = FALSE;
  687.     goto maybe;
  688.  
  689.     /* if flipflop was true, flop it */
  690.  
  691.     flipmaybe:
  692.  
  693. #ifdef macintosh
  694.     SpinMacCursor();
  695. #endif
  696.  
  697.     if (match && cmdflags & CF_FLIP) {
  698.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  699.         str_free(tmps_list[tmps_max]);
  700.         tmps_list[tmps_max--] = Nullstr;
  701.         }
  702.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  703.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
  704.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  705.         }
  706.         else {
  707.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
  708.         if (cmd->c_expr->arg_type == O_FLOP)    /* still toggled? */
  709.             cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
  710.         }
  711.     }
  712.     else if (cmdflags & CF_FLIP) {
  713.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  714.         match = TRUE;                /* force on */
  715.         }
  716.     }
  717.  
  718.     /* at this point, match says whether our expression was true */
  719.  
  720.     maybe:
  721.  
  722. #ifdef macintosh
  723.    SpinMacCursor();
  724. #endif
  725.  
  726.     if (cmdflags & CF_INVERT)
  727.         match = !match;
  728.     if (!match)
  729.         goto next_cmd;
  730.     }
  731. #ifdef TAINT
  732.     tainted = 0;    /* modifier doesn't affect regular expression */
  733. #endif
  734.  
  735.     /* now to do the actual command, if any */
  736.  
  737. #ifdef macintosh
  738.     SpinMacCursor();
  739. #endif
  740.  
  741.     switch (cmd->c_type) {
  742.     case C_NULL:
  743.     fatal("panic: cmd_exec");
  744.     case C_EXPR:            /* evaluated for side effects */
  745.     if (cmd->ucmd.acmd.ac_expr) {    /* more to do? */
  746.         if (gimme == G_ARRAY) {
  747.         lastretstr = Nullstr;
  748.         lastspbase = sp;
  749.         lastsize = newsp - sp;
  750.         if (lastsize < 0)
  751.             lastsize = 0;
  752.         }
  753.         else
  754.         lastretstr = retstr;
  755.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  756.         str_free(tmps_list[tmps_max]);
  757.         tmps_list[tmps_max--] = Nullstr;
  758.         }
  759.         newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
  760.         st = stack->ary_array;    /* possibly reallocated */
  761.         retstr = st[newsp];
  762.     }
  763.     break;
  764.     case C_NSWITCH:
  765.     {
  766.         double value = str_gnum(STAB_STR(cmd->c_stab));
  767.  
  768.         match = (int)value;
  769.         if (value < 0.0) {
  770.         if (((double)match) > value)
  771.             --match;        /* was fractional--truncate other way */
  772.         }
  773.     }
  774.  
  775. #ifdef macintosh
  776.    SpinMacCursor();
  777. #endif
  778.  
  779.     goto doswitch;
  780.     case C_CSWITCH:
  781.     if (multiline) {
  782.         cmd = cmd->c_next;            /* can't assume anything */
  783.         goto tail_recursion_entry;
  784.     }
  785.     match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
  786.       doswitch:
  787.     match -= cmd->ucmd.scmd.sc_offset;
  788.     if (match < 0)
  789.         match = 0;
  790.     else if (match > cmd->ucmd.scmd.sc_max)
  791.         match = cmd->ucmd.scmd.sc_max;
  792.     cmd = cmd->ucmd.scmd.sc_next[match];
  793.     goto tail_recursion_entry;
  794.     case C_NEXT:
  795.     cmd = cmd->ucmd.ccmd.cc_alt;
  796.     goto tail_recursion_entry;
  797.     case C_ELSIF:
  798.     fatal("panic: ELSIF");
  799.     case C_IF:
  800.     oldspat = curspat;
  801.     oldsave = savestack->ary_fill;
  802. #ifdef DEBUGGING
  803.     olddlevel = dlevel;
  804. #endif
  805.     retstr = &str_yes;
  806.     newsp = -2;
  807.     if (cmd->ucmd.ccmd.cc_true) {
  808. #ifdef DEBUGGING
  809.         if (debug) {
  810.         debname[dlevel] = 't';
  811.         debdelim[dlevel] = '_';
  812.         if (++dlevel >= dlmax)
  813.             grow_dlevel();
  814.         }
  815. #endif
  816.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  817.         st = stack->ary_array;    /* possibly reallocated */
  818.         retstr = st[newsp];
  819.     }
  820.     curspat = oldspat;
  821.     if (savestack->ary_fill > oldsave)
  822.         restorelist(oldsave);
  823. #ifdef DEBUGGING
  824.     dlevel = olddlevel;
  825. #endif
  826.     cmd = cmd->ucmd.ccmd.cc_alt;
  827.     goto tail_recursion_entry;
  828.     case C_ELSE:
  829.     oldspat = curspat;
  830.     oldsave = savestack->ary_fill;
  831. #ifdef DEBUGGING
  832.     olddlevel = dlevel;
  833. #endif
  834.     retstr = &str_undef;
  835.     newsp = -2;
  836.     if (cmd->ucmd.ccmd.cc_true) {
  837. #ifdef DEBUGGING
  838.         if (debug) {
  839.         debname[dlevel] = 'e';
  840.         debdelim[dlevel] = '_';
  841.         if (++dlevel >= dlmax)
  842.             grow_dlevel();
  843.         }
  844. #endif
  845.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  846.         st = stack->ary_array;    /* possibly reallocated */
  847.         retstr = st[newsp];
  848.     }
  849.     curspat = oldspat;
  850.     if (savestack->ary_fill > oldsave)
  851.         restorelist(oldsave);
  852. #ifdef DEBUGGING
  853.     dlevel = olddlevel;
  854. #endif
  855.     break;
  856.     case C_BLOCK:
  857.     case C_WHILE:
  858.     if (!(cmdflags & CF_ONCE)) {    /* first time through here? */
  859.         cmdflags |= CF_ONCE;
  860.         if (++loop_ptr >= loop_max) {
  861.         loop_max += 128;
  862.         Renew(loop_stack, loop_max, struct loop);
  863.         }
  864.         loop_stack[loop_ptr].loop_label = cmd->c_label;
  865.         loop_stack[loop_ptr].loop_sp = sp;
  866. #ifdef DEBUGGING
  867.         if (debug & 4) {
  868.         deb("(Pushing label #%d %s)\n",
  869.           loop_ptr, cmd->c_label ? cmd->c_label : "");
  870.         }
  871. #endif
  872.     }
  873. #ifdef JMPCLOBBER
  874.     cmdparm = cmd;
  875. #endif
  876.     match = setjmp(loop_stack[loop_ptr].loop_env);
  877.     if (match) {
  878.         st = stack->ary_array;    /* possibly reallocated */
  879. #ifdef JMPCLOBBER
  880.         cmd = cmdparm;
  881.         cmdflags = cmd->c_flags|CF_ONCE;
  882.         go_to = goto_targ;
  883. #endif
  884.         if (savestack->ary_fill > oldsave)
  885.         restorelist(oldsave);
  886.         switch (match) {
  887.         default:
  888.         fatal("longjmp returned bad value (%d)",match);
  889.         case O_LAST:
  890.         if (lastretstr) {
  891.             retstr = lastretstr;
  892.             newsp = -2;
  893.         }
  894.         else {
  895.             newsp = sp + lastsize;
  896.             retstr = st[newsp];
  897.         }
  898.         curspat = oldspat;
  899.         goto next_cmd;
  900.         case O_NEXT:
  901. #ifdef JMPCLOBBER
  902.         newsp = -2;
  903.         retstr = &str_undef;
  904. #endif
  905.         goto next_iter;
  906.         case O_REDO:
  907. #ifdef DEBUGGING
  908.         dlevel = olddlevel;
  909. #endif
  910. #ifdef JMPCLOBBER
  911.         newsp = -2;
  912.         retstr = &str_undef;
  913. #endif
  914.         goto doit;
  915.         }
  916.     }
  917.     oldspat = curspat;
  918.     oldsave = savestack->ary_fill;
  919. #ifdef DEBUGGING
  920.     olddlevel = dlevel;
  921. #endif
  922.     doit:
  923.     if (cmd->ucmd.ccmd.cc_true) {
  924. #ifdef DEBUGGING
  925.         if (debug) {
  926.         debname[dlevel] = 't';
  927.         debdelim[dlevel] = '_';
  928.         if (++dlevel >= dlmax)
  929.             grow_dlevel();
  930.         }
  931. #endif
  932.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  933.         st = stack->ary_array;    /* possibly reallocated */
  934.         retstr = st[newsp];
  935.     }
  936.     /* actually, this spot is rarely reached anymore since the above
  937.      * cmd_exec() returns through longjmp().  Hooray for structure.
  938.      */
  939.       next_iter:
  940. #ifdef DEBUGGING
  941.     dlevel = olddlevel;
  942. #endif
  943.     if (cmd->ucmd.ccmd.cc_alt) {
  944. #ifdef DEBUGGING
  945.         if (debug) {
  946.         debname[dlevel] = 'a';
  947.         debdelim[dlevel] = '_';
  948.         if (++dlevel >= dlmax)
  949.             grow_dlevel();
  950.         }
  951. #endif
  952.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  953.         st = stack->ary_array;    /* possibly reallocated */
  954.         retstr = st[newsp];
  955.     }
  956.       finish_while:
  957.     curspat = oldspat;
  958.     if (savestack->ary_fill > oldsave) {
  959.         if (cmdflags & CF_TERM) {
  960.         for (match = sp + 1; match <= newsp; match++)
  961.             st[match] = str_mortal(st[match]);
  962.         retstr = st[newsp];
  963.         }
  964.         restorelist(oldsave);
  965.     }
  966. #ifdef DEBUGGING
  967.     dlevel = olddlevel - 1;
  968. #endif
  969.     if (cmd->c_type != C_BLOCK)
  970.         goto until_loop;    /* go back and evaluate conditional again */
  971.     }
  972.     if (cmdflags & CF_LOOP) {
  973.     cmdflags |= CF_COND;        /* now test the condition */
  974. #ifdef DEBUGGING
  975.     dlevel = entdlevel;
  976. #endif
  977.     goto until_loop;
  978.     }
  979.   next_cmd:
  980.  
  981. #ifdef macintosh
  982.     SpinMacCursor();
  983. #endif
  984.  
  985.     if (cmdflags & CF_ONCE) {
  986. #ifdef DEBUGGING
  987.     if (debug & 4) {
  988.         tmps = loop_stack[loop_ptr].loop_label;
  989.         deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
  990.     }
  991. #endif
  992.     loop_ptr--;
  993.     if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY &&
  994.       savestack->ary_fill > aryoptsave)
  995.         restorelist(aryoptsave);
  996.     }
  997.     cmd = cmd->c_next;
  998.     goto tail_recursion_entry;
  999. }
  1000.  
  1001. #ifdef DEBUGGING
  1002. #  ifndef I_VARARGS
  1003. /*VARARGS1*/
  1004. void deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
  1005. char *pat;
  1006. {
  1007.     register int i;
  1008.  
  1009. #ifdef macintosh
  1010.     fprintf(perldbg,"%-4ld",(long)curcmd->c_line);
  1011.     for (i=0; i<dlevel; i++)
  1012.     fprintf(perldbg,"%c%c ",debname[i],debdelim[i]);
  1013.     fprintf(perldbg,pat,a1,a2,a3,a4,a5,a6,a7,a8);
  1014. #else
  1015.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  1016.     for (i=0; i<dlevel; i++)
  1017.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  1018.     fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
  1019. #endif
  1020. }
  1021. #  else
  1022. /*VARARGS1*/
  1023. void deb(va_alist)
  1024. va_dcl
  1025. {
  1026.     va_list args;
  1027.     char *pat;
  1028.     register int i;
  1029.  
  1030.     va_start(args);
  1031.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  1032.     for (i=0; i<dlevel; i++)
  1033.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  1034.  
  1035.     pat = va_arg(args, char *);
  1036.     (void) vfprintf(stderr,pat,args);
  1037.     va_end( args );
  1038. }
  1039. #  endif
  1040. #endif
  1041.  
  1042. int
  1043. copyopt(cmd,which)
  1044. register CMD *cmd;
  1045. register CMD *which;
  1046. {
  1047.     cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
  1048.     cmd->c_flags |= which->c_flags;
  1049.     cmd->c_short = which->c_short;
  1050.     cmd->c_slen = which->c_slen;
  1051.     cmd->c_stab = which->c_stab;
  1052.     return cmd->c_flags;
  1053. }
  1054.  
  1055. ARRAY *
  1056. saveary(stab)
  1057. STAB *stab;
  1058. {
  1059.     register STR *str;
  1060.  
  1061.     str = Str_new(10,0);
  1062.     str->str_state = SS_SARY;
  1063.     str->str_u.str_stab = stab;
  1064.     if (str->str_ptr) {
  1065.     Safefree(str->str_ptr);
  1066.     str->str_ptr = Nullch;
  1067.     str->str_len = 0;
  1068.     }
  1069.     str->str_ptr = (char*)stab_array(stab);
  1070.     (void)apush(savestack,str); /* save array ptr */
  1071.     stab_xarray(stab) = Null(ARRAY*);
  1072.     return stab_xarray(aadd(stab));
  1073. }
  1074.  
  1075. HASH *
  1076. savehash(stab)
  1077. STAB *stab;
  1078. {
  1079.     register STR *str;
  1080.  
  1081.     str = Str_new(11,0);
  1082.     str->str_state = SS_SHASH;
  1083.     str->str_u.str_stab = stab;
  1084.     if (str->str_ptr) {
  1085.     Safefree(str->str_ptr);
  1086.     str->str_ptr = Nullch;
  1087.     str->str_len = 0;
  1088.     }
  1089.     str->str_ptr = (char*)stab_hash(stab);
  1090.     (void)apush(savestack,str); /* save hash ptr */
  1091.     stab_xhash(stab) = Null(HASH*);
  1092.     return stab_xhash(hadd(stab));
  1093. }
  1094.  
  1095. void
  1096. saveitem(item)
  1097. register STR *item;
  1098. {
  1099.     register STR *str;
  1100.  
  1101.     (void)apush(savestack,item);        /* remember the pointer */
  1102.     str = Str_new(12,0);
  1103.     str_sset(str,item);
  1104.     (void)apush(savestack,str);            /* remember the value */
  1105. }
  1106.  
  1107. void
  1108. saveint(intp)
  1109. int *intp;
  1110. {
  1111.     register STR *str;
  1112.  
  1113.     str = Str_new(13,0);
  1114.     str->str_state = SS_SINT;
  1115.     str->str_u.str_useful = (long)*intp;    /* remember value */
  1116.     if (str->str_ptr) {
  1117.     Safefree(str->str_ptr);
  1118.     str->str_len = 0;
  1119.     }
  1120.     str->str_ptr = (char*)intp;        /* remember pointer */
  1121.     (void)apush(savestack,str);
  1122. }
  1123.  
  1124. void
  1125. savelong(longp)
  1126. long *longp;
  1127. {
  1128.     register STR *str;
  1129.  
  1130.     str = Str_new(14,0);
  1131.     str->str_state = SS_SLONG;
  1132.     str->str_u.str_useful = *longp;        /* remember value */
  1133.     if (str->str_ptr) {
  1134.     Safefree(str->str_ptr);
  1135.     str->str_len = 0;
  1136.     }
  1137.     str->str_ptr = (char*)longp;        /* remember pointer */
  1138.     (void)apush(savestack,str);
  1139. }
  1140.  
  1141. void
  1142. savesptr(sptr)
  1143. STR **sptr;
  1144. {
  1145.     register STR *str;
  1146.  
  1147.     str = Str_new(15,0);
  1148.     str->str_state = SS_SSTRP;
  1149.     str->str_magic = *sptr;        /* remember value */
  1150.     if (str->str_ptr) {
  1151.     Safefree(str->str_ptr);
  1152.     str->str_len = 0;
  1153.     }
  1154.     str->str_ptr = (char*)sptr;        /* remember pointer */
  1155.     (void)apush(savestack,str);
  1156. }
  1157.  
  1158. void
  1159. savenostab(stab)
  1160. STAB *stab;
  1161. {
  1162.     register STR *str;
  1163.  
  1164.     str = Str_new(16,0);
  1165.     str->str_state = SS_SNSTAB;
  1166.     str->str_magic = (STR*)stab;    /* remember which stab to free */
  1167.     (void)apush(savestack,str);
  1168. }
  1169.  
  1170. void
  1171. savehptr(hptr)
  1172. HASH **hptr;
  1173. {
  1174.     register STR *str;
  1175.  
  1176.     str = Str_new(17,0);
  1177.     str->str_state = SS_SHPTR;
  1178.     str->str_u.str_hash = *hptr;    /* remember value */
  1179.     if (str->str_ptr) {
  1180.     Safefree(str->str_ptr);
  1181.     str->str_len = 0;
  1182.     }
  1183.     str->str_ptr = (char*)hptr;        /* remember pointer */
  1184.     (void)apush(savestack,str);
  1185. }
  1186.  
  1187. void
  1188. saveaptr(aptr)
  1189. ARRAY **aptr;
  1190. {
  1191.     register STR *str;
  1192.  
  1193.     str = Str_new(17,0);
  1194.     str->str_state = SS_SAPTR;
  1195.     str->str_u.str_array = *aptr;    /* remember value */
  1196.     if (str->str_ptr) {
  1197.     Safefree(str->str_ptr);
  1198.     str->str_len = 0;
  1199.     }
  1200.     str->str_ptr = (char*)aptr;        /* remember pointer */
  1201.     (void)apush(savestack,str);
  1202. }
  1203.  
  1204. void
  1205. savelist(sarg,maxsarg)
  1206. register STR **sarg;
  1207. int maxsarg;
  1208. {
  1209.     register STR *str;
  1210.     register int i;
  1211.  
  1212.     for (i = 1; i <= maxsarg; i++) {
  1213.     (void)apush(savestack,sarg[i]);        /* remember the pointer */
  1214.     str = Str_new(18,0);
  1215.     str_sset(str,sarg[i]);
  1216.     (void)apush(savestack,str);            /* remember the value */
  1217.     sarg[i]->str_u.str_useful = -1;
  1218.     }
  1219. }
  1220.  
  1221. void
  1222. restorelist(base)
  1223. int base;
  1224. {
  1225.     register STR *str;
  1226.     register STR *value;
  1227.     register STAB *stab;
  1228.  
  1229.     if (base < -1)
  1230.     fatal("panic: corrupt saved stack index");
  1231.     while (savestack->ary_fill > base) {
  1232.     value = apop(savestack);
  1233.     switch (value->str_state) {
  1234.     case SS_NORM:                /* normal string */
  1235.     case SS_INCR:
  1236.         str = apop(savestack);
  1237.         str_replace(str,value);
  1238.         STABSET(str);
  1239.         break;
  1240.     case SS_SARY:                /* array reference */
  1241.         stab = value->str_u.str_stab;
  1242.         afree(stab_xarray(stab));
  1243.         stab_xarray(stab) = (ARRAY*)value->str_ptr;
  1244.         value->str_ptr = Nullch;
  1245.         str_free(value);
  1246.         break;
  1247.     case SS_SHASH:                /* hash reference */
  1248.         stab = value->str_u.str_stab;
  1249. #ifndef macintosh
  1250.         (void)hfree(stab_xhash(stab), FALSE);
  1251. #else
  1252.         hfree(stab_xhash(stab), FALSE);
  1253. #endif
  1254.         stab_xhash(stab) = (HASH*)value->str_ptr;
  1255.         value->str_ptr = Nullch;
  1256.         str_free(value);
  1257.         break;
  1258.     case SS_SINT:                /* int reference */
  1259.         *((int*)value->str_ptr) = (int)value->str_u.str_useful;
  1260.         value->str_ptr = Nullch;
  1261.         str_free(value);
  1262.         break;
  1263.     case SS_SLONG:                /* long reference */
  1264.         *((long*)value->str_ptr) = value->str_u.str_useful;
  1265.         value->str_ptr = Nullch;
  1266.         str_free(value);
  1267.         break;
  1268.     case SS_SSTRP:                /* STR* reference */
  1269.         *((STR**)value->str_ptr) = value->str_magic;
  1270.         value->str_magic = Nullstr;
  1271.         value->str_ptr = Nullch;
  1272.         str_free(value);
  1273.         break;
  1274.     case SS_SHPTR:                /* HASH* reference */
  1275.         *((HASH**)value->str_ptr) = value->str_u.str_hash;
  1276.         value->str_ptr = Nullch;
  1277.         str_free(value);
  1278.         break;
  1279.     case SS_SAPTR:                /* ARRAY* reference */
  1280.         *((ARRAY**)value->str_ptr) = value->str_u.str_array;
  1281.         value->str_ptr = Nullch;
  1282.         str_free(value);
  1283.         break;
  1284.     case SS_SNSTAB:
  1285.         stab = (STAB*)value->str_magic;
  1286.         value->str_magic = Nullstr;
  1287. #ifndef macintosh
  1288.         (void)stab_clear(stab);
  1289. #else
  1290.         stab_clear(stab);
  1291. #endif
  1292.         str_free(value);
  1293.         break;
  1294.     case SS_SCSV:                /* callsave structure */
  1295.         {
  1296.         CSV *csv = (CSV*) value->str_ptr;
  1297.  
  1298.         curcmd = csv->curcmd;
  1299.         curcsv = csv->curcsv;
  1300.         csv->sub->depth = csv->depth;
  1301.         if (csv->hasargs) {        /* put back old @_ */
  1302.             afree(csv->argarray);
  1303.             stab_xarray(defstab) = csv->savearray;
  1304.         }
  1305.         str_free(value);
  1306.         }
  1307.         break;
  1308.     default:
  1309.         fatal("panic: restorelist inconsistency");
  1310.     }
  1311.     }
  1312. }
  1313.  
  1314. #ifdef DEBUGGING
  1315. void
  1316. grow_dlevel()
  1317. {
  1318.     dlmax += 128;
  1319.     Renew(debname, dlmax, char);
  1320.     Renew(debdelim, dlmax, char);
  1321. }
  1322. #endif
  1323.